#include <stdio.h>

int is_leap(int year);
int days_month(int month, int year);


int main(void)
{
    int month, year, i;

    printf("输入月数和年份：\n");
    scanf("%d%d", &month, &year);

    if (month <= 0 || month > 12 || year <= 0 || year > 9999) {
        printf("数据格式错误！！！\n");
        return 0;
    }

    /* 打印日历头 */
    char* m[12] = {"一", "二", "三", "四", "五", "六", "七", "八", "九", "十", "十一", "十二"}; // 可使用switch实现打印，效果相同
    printf("      %s月 %d\n", m[month - 1], year);
    printf("日 一 二 三 四 五 六\n");

    /* 计算该月份有多少天 */
    int days = days_month(month, year);

    /* 计算该月份的第一天是星期几 */
    if (month < 3) {
        year--;
        month += 12;
    }
    // 基姆拉尔森计算公式，0表示周日，1~6表示周一到周六
    int week = (1 + 2 * month + 3 * (month + 1) / 5 + year + year / 4 - year / 100 + year / 400 + 1) % 7;

    /* 打印日历 */
    if (week != 0) {
        for (i = 1; i <= week; i++) 
            printf("   "); // 三个空格
    }

    for (i = 1; i <= days; i++) { // 按照天数依次打印
        printf("%2d ", i);
        if (week == 6) // 周六之后则换行
            printf("\n");
        week = (week + 1) % 7;
    }

    printf("\n");

    return 0;
}


/* 判断是否是闰年 */
int is_leap(int year)
{
    return (year % 4 == 0 && year % 100 != 0) || year % 400 == 0; 
}


/* 计算月份的天数 */
int days_month(int month, int year)
{
	int ret;

	if (1 == month || 3 == month || 5 == month || 7 == month || \
			8 == month || 10 == month || 12 == month)
		ret = 31;
	else if (4 == month || 6 == month || 9 == month || 11 == month)
		ret = 30;
	else if (2 == month) {
	 	// 判断year是否为闰年,调用（使用）闰年的函数
		/*
		 函数的调用
		 	函数调用的时候，传递的参数仅仅是值的传递，不是变量的传递
			days_month函数参数year与is_leap函数的year没有任何关联，仅仅是名字相同的两个不同变量
			当函数调用，程序会将执行的地址切换到调用函数，当函数结束后的结果值return的值就是函数调用的结果
		 */
		ret = 28 + is_leap(year);
	} else
		ret = -1;

	return ret;
}

